package com.party.jackclientandroid;

import android.app.Application;
import android.content.Context;
import android.support.multidex.MultiDex;
import android.text.TextUtils;
import android.view.View;

import com.alibaba.fastjson.JSON;
import com.facebook.stetho.Stetho;
import com.orhanobut.logger.AndroidLogAdapter;
import com.orhanobut.logger.Logger;
import com.party.jackclientandroid.bean.ShopClassification;
import com.party.jackclientandroid.bean.User;
import com.party.jackclientandroid.controller.AMapController;
import com.party.jackclientandroid.controller.TCInitController;
import com.party.jackclientandroid.event.AMapBeanEvent;
import com.party.jackclientandroid.imageloader.GlideLoaderFactory;
import com.party.jackclientandroid.imageloader.ImageLoaderFactory;
import com.party.jackclientandroid.loadviewhelper.load.LoadViewHelper;
import com.party.jackclientandroid.okhttp.CacheUtils;
import com.party.jackclientandroid.okhttp.HttpLogger;
import com.party.jackclientandroid.okhttp.OkHttpUtils;
import com.party.jackclientandroid.utils.NetworkUtils;
import com.party.jackclientandroid.utils.SPUtils;
import com.tencent.bugly.Bugly;
import com.tencent.bugly.crashreport.CrashReport;
import com.uuzuche.lib_zxing.activity.ZXingLibrary;

import org.greenrobot.eventbus.EventBus;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.concurrent.TimeUnit;

import cn.jpush.android.api.JPushInterface;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;

/**
 * <a href="https://www.jianshu.com/p/03c28e64b636">Android的multidex带来NoClassDefFoundError?</a><br>
 * Created by Tangxb on 2017/2/14.
 */

public class MApplication extends Application {

    private ImageLoaderFactory imageLoaderFactory;
    private Stack<WeakReference<BaseActivity>> mActivityStack;
    private User mUser;
    private String mToken;
    private List<ShopClassification> shopClassificationList;
    /**
     * 地理位置相关的
     */
    private AMapBeanEvent aMapBeanEvent;

    public AMapBeanEvent getMap() {
        return aMapBeanEvent;
    }

    public void setMap(AMapBeanEvent aMapBeanEvent) {
        this.aMapBeanEvent = aMapBeanEvent;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        init();
        initDebugSth();
    }


    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(base);
    }

    public void initDebugSth() {
        CrashReport.initCrashReport(getApplicationContext(), "ac181e8784", false);
        Stetho.initializeWithDefaults(this);
    }

    private void init() {
        initTCSdk();
        initZxing();
        initLoadView();
        initDaoManager();
        NetworkUtils.setContext(this);
        CacheUtils.setContext(this);
        initOkHttpUtils();
        initImageLoaderFactory();
        initBugly();
        Logger.addLogAdapter(new AndroidLogAdapter());
        initActivityStack();
        JPushInterface.setDebugMode(true);
        JPushInterface.init(this);
    }

    public void initTCSdk() {
        TCInitController.initTCSdk(this);
    }

    private void initZxing() {
        ZXingLibrary.initDisplayOpinion(this);
    }

    private void initLoadView() {
        LoadViewHelper.getBuilder()
                .setLoadEmpty(R.layout.load_empty)
                .setLoadError(R.layout.load_error)
                .setLoadIng(R.layout.load_ing);
    }

    private void initDaoManager() {

    }

    private void initActivityStack() {
        mActivityStack = new Stack<>();
    }

    private void initOkHttpUtils() {
        HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(new HttpLogger());
        logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(10 * 1000L, TimeUnit.MILLISECONDS)
                .readTimeout(60 * 1000L, TimeUnit.MILLISECONDS)
                .writeTimeout(60 * 1000L, TimeUnit.MILLISECONDS)
//                .addInterceptor(logInterceptor)
                .build();
        OkHttpUtils.initClient(okHttpClient);
    }

    private void initImageLoaderFactory() {
        imageLoaderFactory = new GlideLoaderFactory();
    }

    public ImageLoaderFactory getImageLoaderFactory() {
        return imageLoaderFactory;
    }


    private void initBugly() {
        Context context = getApplicationContext();
        // 获取当前包名
        String packageName = context.getPackageName();
        // 获取当前进程名
        String processName = getProcessName(android.os.Process.myPid());
        // 设置是否为上报进程
        CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(context);
        strategy.setUploadProcess(processName == null || processName.equals(packageName));
        // 初始化Bugly
        CrashReport.initCrashReport(context, BuildConfig.BUG_APP_ID, BuildConfig.DEBUG, strategy);
    }

    /**
     * 获取进程号对应的进程名
     *
     * @param pid 进程号
     * @return 进程名
     */
    private String getProcessName(int pid) {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader("/proc/" + pid + "/cmdline"));
            String processName = reader.readLine();
            if (!TextUtils.isEmpty(processName)) {
                processName = processName.trim();
            }
            return processName;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException exception) {
                exception.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 添加Activity到ActivityStack里面
     *
     * @param activity
     */
    public void pushActivity(BaseActivity activity) {
        mActivityStack.push(new WeakReference<>(activity));
    }

    /**
     * 移除ActivityStack栈顶元素
     */
    public void removeTopActivity() {
        mActivityStack.pop();
    }

    /**
     * 移除自身之外的其他Activity并且finish
     *
     * @param baseActivity
     */
    public void finishOtherActivity(BaseActivity baseActivity) {
        List<WeakReference<BaseActivity>> weakReferenceList = new ArrayList<>();
        for (WeakReference<BaseActivity> reference : mActivityStack) {
            if (reference != null && reference.get() != null) {
                if (!reference.get().getClass().getName().equals(baseActivity.getClass().getName())) {
                    weakReferenceList.add(reference);
                }
            }
        }
        for (WeakReference<BaseActivity> reference : weakReferenceList) {
            reference.get().finish();
        }
    }

    public void removeActivity(BaseActivity baseActivity) {
        WeakReference<BaseActivity> weak = null;
        for (WeakReference<BaseActivity> reference : mActivityStack) {
            if (reference != null && reference.get() != null) {
                if (reference.get().getClass().getName().equals(baseActivity.getClass().getName())) {
                    weak = reference;
                    break;
                }
            }
        }
        if (weak != null) {
            mActivityStack.remove(weak);
        }
    }

    public void finishActivity(Class<?> cls) {
        WeakReference<BaseActivity> weak = null;
        for (WeakReference<BaseActivity> reference : mActivityStack) {
            if (reference != null && reference.get() != null) {
                if (reference.get().getClass().getName().equals(cls.getName())) {
                    weak = reference;
                    break;
                }
            }
        }
        if (weak != null) {
            weak.get().finish();
        }
    }


    public boolean hasContainActivity(Class<?> cls) {
        for (WeakReference<BaseActivity> reference : mActivityStack) {
            if (reference != null && reference.get() != null) {
                if (reference.get().getClass().getName().equals(cls.getName())) {
                    return true;
                }
            }
        }
        return false;
    }

    public BaseActivity getActivity(Class<?> cls) {
        for (WeakReference<BaseActivity> reference : mActivityStack) {
            if (reference != null && reference.get() != null) {
                if (reference.get().getClass().getName().equals(cls.getName())) {
                    return reference.get();
                }
            }
        }
        return null;
    }

    public BaseActivity getTopActivity() {
        WeakReference<BaseActivity> weak = null;
        try {
            weak = mActivityStack.peek();
        } catch (Exception e) {
        }
        if (weak != null) {
            return weak.get();
        }
        return null;
    }

    /**
     * @param lastIndex 0:栈顶 1: 栈顶下一个
     */
    public void removeStackSecondActivity(int lastIndex) {
        int size = mActivityStack.size();
        if (size == 0 || lastIndex > size - 1) return;
        try {
            WeakReference<BaseActivity> reference = mActivityStack.elementAt(size - 1 - lastIndex);
            if (reference != null && reference.get() != null && !reference.get().getClass().getName().equals(MainActivity.class.getName())) {
                reference.get().finish();
            }
        } catch (Exception e) {
        }
    }

    public void post(Object object) {
        EventBus.getDefault().post(object);
    }

    public void setUser(User user) {
        mUser = user;
        String objectStr = JSON.toJSONString(user);
        SPUtils.put(this, "current_user", objectStr);
    }

    public User getUser() {
        if (mUser == null) mUser = SPUtils.getObject(this, "current_user", User.class);
        //防止空指针异常
        if (mUser == null) return new User();
        return mUser;
    }

    public String getToken() {
        if (mToken == null) mToken = getUser().getToken();
        return mToken;
    }

    public void cleanUser() {
        mToken = null;
        mUser = null;
        SPUtils.remove(this, "current_user");
    }

    public List<ShopClassification> getShopClassificationList() {
        return shopClassificationList;
    }

    public void setShopClassificationList(List<ShopClassification> shopClassificationList) {
        this.shopClassificationList = shopClassificationList;
    }

    @Override
    public void onTerminate() {
        // 程序终止的时候执行
        super.onTerminate();
        EventBus.getDefault().removeAllStickyEvents();
    }

    public AMapController updateMap(View.OnClickListener finishListener) {
        AMapController mapController = new AMapController(getTopActivity());
        mapController.startLocation();
        mapController.setFinishListener((View v) -> {
            finishListener.onClick(v);
            mapController.destroyLocation();
        });
        return mapController;
    }
}
